﻿#region License
/* ****************************************
 * Allrights reserved by BlueLotus7 
 * 
 * Last updated: 2009-10-01
 * 
 * BlueLotus7@126.com
 * BlueLotus7@vip.qq.com
 * ****************************************/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using BlueLotus7.Common;
using System.Runtime.Serialization;
using System.Threading;

namespace BlueLotus7.Contract
{  

    [DataContract]
    [KnownType(typeof(TaskStatus))]
    [KnownType(typeof(BaseTask))]
    public abstract class BaseTask : ITask
    {
        protected Guid identity;
        protected string title;
        protected string description;
        protected object taskObject;
        protected DateTime createdStamp;
        protected DateTime? lastSavedStamp;
        protected DateTime? lastExecutedStamp;
        protected TaskStatus taskStatus;

        protected bool continueToExecute = false;
        protected object continueToExecuteLocker = new object();
        protected bool threadUsing = false;
        protected object threadUsingLocker = new object();

        protected Thread thread;

        /// <summary>
        /// Constructor
        /// </summary>
        protected BaseTask() { }

        /// <summary>
        /// Constructor
        /// </summary>
        protected BaseTask(string title)
        {
            this.identity = Guid.NewGuid();
            this.title = title;
            this.description = string.Empty;
            createdStamp = DateTime.Now;
            this.taskStatus = TaskStatus.Created;
        }

        #region ITask Members

        /// <summary>
        /// The identity
        /// </summary>
        public Guid Identity
        {
            get { return identity; }
        }

        /// <summary>
        /// The title
        /// </summary>
        public string Title
        {
            get { return title; }
        }

        /// <summary>
        /// The description
        /// </summary>
        public string Description
        {
            get { return description; }
            set { description = value; }
        }

        /// <summary>
        /// The created stamp.
        /// </summary>
        public DateTime CreatedStamp
        {
            get { return createdStamp; }
        }

        /// <summary>
        /// The last saved stamp.
        /// </summary>
        public DateTime? LastSavedStamp
        {
            get { return lastSavedStamp; }
        }

        /// <summary>
        /// The last executed stamp;
        /// </summary>
        public DateTime? LastExecutedStamp
        {
            get { return lastExecutedStamp; }
        }

        /// <summary>
        /// The task status.
        /// </summary>
        public TaskStatus TaskStatus
        {
            get { return taskStatus; }
            set { taskStatus = value; }
        }

        /// <summary>
        /// Indicates thread is using.
        /// </summary>
        public bool ThreadUsing
        {
            get
            {
                lock (threadUsingLocker)
                {
                    return threadUsing;
                }
            }
            set
            {
                if (thread != null && thread.ManagedThreadId == Thread.CurrentThread.ManagedThreadId)
                {
                    threadUsing = value;
                }
            }
        }

        /// <summary>
        /// Starts to execute task.
        /// </summary>
        public void Start()
        {
            if (!continueToExecute)
            {
                continueToExecute = true;
                thread = new Thread(new ParameterizedThreadStart(Execute));
                thread.IsBackground = true;
                thread.Start(this);
            }
        }

        /// <summary>
        /// Stop executing task.
        /// </summary>
        public void Stop()
        {
            lock (continueToExecuteLocker)
            {
                continueToExecute = false;
            }
        }

        //protected void Finish()
        //{
        //    lock (continueToExecuteLocker)
        //    {
        //        continueToExecute = false;
        //    }
        //}

        /// <summary>
        /// Executes the task.
        /// </summary>
        /// <param name="hoster"></param>
        protected void Execute(object hoster)
        {
            ITask task = null;
            lock (threadUsingLocker)
            {
                if (!task.ThreadUsing)
                {
                    task = hoster as ITask;
                    if (task == null)
                    {
                        return;
                    }
                    task.ThreadUsing = true;
                    task.TaskStatus = TaskStatus.Executing;
                }
            }

            try
            {
                bool executeResult = false;

                while (continueToExecute)
                {
                    lock (continueToExecuteLocker)
                    {
                        executeResult = Execute();
                        if (executeResult)
                        {
                            continueToExecute = false;
                        }
                    }
                }

                if (executeResult)
                {
                    task.TaskStatus = TaskStatus.Done;
                }
                else
                {
                    task.TaskStatus = TaskStatus.Ready;
                }
            }
            catch (Exception exception)
            {
                task.TaskStatus = TaskStatus.ExceptionThown;
                HandleException(exception);
            }
            finally
            {
                task.ThreadUsing = false;
            }
        }

        #endregion

        protected virtual bool Execute()
        {
            return false;
        }

        protected virtual void HandleException(Exception exception)
        {

        }
    }
}
